package view
{
	
	import flash.display.*;
	import flash.events.*;
	import flash.text.TextField;
	
	import model.BasePx;
	import manager.ProxyMgr;
	import event.EvtDispatcher;
	
	/**
	 * -- BaseView --
	 * @desc	base class of all view classes, including some base methods
	 * @author	Aqua (built on 2011-11-08)
	 */
	
	public class BaseView
	{
		//---------------------//
		//     Constructor     //
		//---------------------//
		
		/**************************************************************************
		 * -- BaseView --
		 * @desc		constructor
		 * @param		main view object of this view class
		 *************************************************************************/
		public function BaseView(viewComponent:DisplayObjectContainer):void
		{
			_viewComponent = viewComponent;
			_addCmdList = {};
			_clickCmdList = { };
			_evt = EvtDispatcher.instance;
		}
		
		
		//-----------------//
		//     Publics     //
		//-----------------//
		
		/**************************************************************************
		 * -- (getter) viewComponent --
		 * @desc		get the main view object of this view class
		 * @return		main view object of this view class
		 *************************************************************************/
		public function get viewComponent():DisplayObject
		{
			return _viewComponent;
		}
		
		/**************************************************************************
		 * -- onAdd --
		 * @desc		prepare to be added to stage, mainly adding event listeners
		 *************************************************************************/
		public function onAdd():void
		{
			_viewComponent.addEventListener(Event.ADDED, onEvent, false, 0, true);
			_viewComponent.addEventListener(MouseEvent.CLICK, onEvent, false, 0, true);
			onRefresh();
		}
		
		/**************************************************************************
		 * -- onRemove --
		 * @desc		prepare to be removed from stage
		 *************************************************************************/
		public function onRemove():void
		{
			_viewComponent.removeEventListener(Event.ADDED, onEvent);
			_viewComponent.removeEventListener(MouseEvent.CLICK, onEvent);
		}
		
		/**************************************************************************
		 * -- onRefresh --
		 * @desc		refresh whole object
		 *************************************************************************/
		public function onRefresh():void
		{
			dispatchAddEvent(_viewComponent);
		}
		
		
		//--------------------//
		//     Protecteds     //
		//--------------------//
		
		/**************************************************************************
		 * -- getPx --
		 * @desc		get proxy from proxy manager
		 * @param		(name) name of the proxy
		 * @return		the proxy
		 *************************************************************************/
		protected function getPx(name:String):BasePx
		{
			return ProxyMgr.instance.getProxy(name);
		}
		
		/**************************************************************************
		 * -- getChild --
		 * @desc		get the child with specified name in a container
		 * @param		(container) container of the child
		 * @param		(name) name of the child
		 * @return		the child
		 *************************************************************************/
		protected function getChild(container:DisplayObjectContainer, name:String):DisplayObject
		{
			var child:DisplayObject;
			var i:int;
			
			i = container.numChildren - 1;
			while (i >= 0)
			{
				child = container.getChildAt(i);
				if (child && child.name == name)
				{
					return child;
				}
				i --;
			}
			
			return null;
		}
		
		/**************************************************************************
		 * -- getIndex --
		 * @desc		get index of a display object (e.g. index of "btn_3" is 3)
		 * @param		(display) the specified display object
		 * @return		index of display object
		 *************************************************************************/
		protected function getIndex(display:DisplayObject):int
		{
			var regExp:RegExp;
			var instanceRegExp:RegExp;
			
			if (! display)
			{
				return 0;
			}
			
			regExp = /[0-9]{1,3}/;			
			instanceRegExp = /instance/;
			
			while (instanceRegExp.exec(display.name) || ! regExp.exec(display.name))
			{
				display = display.parent;
				if (! display)
				{
					display = new MovieClip();
					display.name = "container_0";
					break;
				}
			}
			
			return RegExp(/[0-9]{1,3}/).exec(display.name);
		}
		
		/**************************************************************************
		 * -- makeBtn --
		 * @desc		initialize button
		 * @param		(display) button object
		 *************************************************************************/
		protected function makeBtn(display:DisplayObject):void
		{
			var mc:MovieClip;
			
			mc = MovieClip(display);
			mc.buttonMode = true;
			mc.mouseChildren = false;
			mc.addEventListener(MouseEvent.ROLL_OVER, onRollOver, false, 0, true);
			mc.addEventListener(MouseEvent.ROLL_OUT, onRollOut, false, 0, true);
			mc.gotoAndStop("up");
		}
		
		/**************************************************************************
		 * -- onRollOver --
		 * @desc		handler of roll over event
		 * @param		(e) event infomation
		 *************************************************************************/
		protected function onRollOver(e:MouseEvent):void
		{
			MovieClip(e.target).gotoAndStop("over");
		}
		
		/**************************************************************************
		 * -- onRollOut --
		 * @desc		handler of roll out event
		 * @param		(e) event infomation
		 *************************************************************************/
		protected function onRollOut(e:MouseEvent):void
		{
			MovieClip(e.target).gotoAndStop("up");
		}
		
		/**************************************************************************
		 * -- dispatchAddEvent --
		 * @desc		dispatch added event on a display object and all its children
		 * @param		(display) target display object
		 *************************************************************************/
		protected function dispatchAddEvent(display:DisplayObject):void
		{
			var i:int;
			var numChildren:int;
			var child:DisplayObject;
			var container:DisplayObjectContainer;
			
			display.dispatchEvent(new Event(Event.ADDED, true));
			
			if (display is DisplayObjectContainer)
			{
				container = DisplayObjectContainer(display);
				numChildren = container.numChildren;
				i = 0;
				
				while (i < numChildren)
				{
					child = container.getChildAt(i);
						
					if (child)
					{
						dispatchAddEvent(child);
					}
						
					i ++;
				}
			}
		}
		
		/**************************************************************************
		 * -- onEvent --
		 * @desc		ADDED and CLICK event handler
		 * @param		(e) event information
		 *************************************************************************/
		protected function onEvent(e:Event):void
		{
			var dispName:String;
			
			e.stopPropagation();
			_display = DisplayObject(e.target);
			dispName = _display.name;
			
			switch(e.type)
			{
				case Event.ADDED:
					if (_addCmdList[dispName])
					{
						_addCmdList[dispName]();
					}
					break;
				case MouseEvent.CLICK:
					if (_clickCmdList[dispName])
					{
						_clickCmdList[dispName]();
					}
					break;
				default:
					break;
			}
		}
		
		/**************************************************************************
		 * -- addAddCmd --
		 * @desc		add command to _addCmdList
		 * @param		(cmd) name of the command
		 * @param		(handler) handler of the command
		 *************************************************************************/
		protected function addAddCmd(cmd:String, handler:Function):void
		{
			if (! _addCmdList[cmd])
			{
				_addCmdList[cmd] = handler;
			}
		}
		
		/**************************************************************************
		 * -- addClickCmd --
		 * @desc		add command to _clickCmdList
		 * @param		(cmd) name of the command
		 * @param		(handler) handler of the command
		 *************************************************************************/
		protected function addClickCmd(cmd:String, handler:Function):void
		{
			if (! _clickCmdList[cmd])
			{
				_clickCmdList[cmd] = handler;
			}
		}
		
		
		public static const VIEW_NAME	:String	= "BASE_VIEW";
		public static const LAYER_INDEX	:int	= 0;
		
		protected var _viewComponent	:DisplayObjectContainer;
		protected var _addCmdList		:Object;
		protected var _clickCmdList		:Object;
		protected var _display			:DisplayObject;
		protected var _evt				:EvtDispatcher;
	}
	
}